package com.fsh.lingsp.common.user.service.impl;

import com.fsh.lingsp.common.common.constant.RedisKey;
import com.fsh.lingsp.common.common.utils.JwtUtils;
import com.fsh.lingsp.common.common.utils.RedisUtils;
import com.fsh.lingsp.common.user.service.LoginService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.util.Objects;
import java.util.concurrent.*;

@Service
public class LoginServiceImpl implements LoginService {

    @Autowired
    private JwtUtils jwtUtils;

    /**
     * 校验token是不是有效
     *
     * @param token
     * @return
     */
    @Override
    public boolean verify(String token) {
        return false;
    }

    /**
     * 异步 刷新token有效期：两种异步方法
     * ①:使用JUC的线程池
     * ②:使用@Async注解
     *
     * @param token
     */
    @Override
    @Async
    public void renewalTokenIfNecessary(String token) {
        //拿到uid，获取key
        Long uid = getValidUid(token);
        String userTokenKey = RedisKey.getKey(RedisKey.USER_TOKEN_STR, uid);
        //获取key的过期时间。 key不存在则为-2
        Long expireDays = RedisUtils.getExpire(userTokenKey,TimeUnit.DAYS);
        if (expireDays==-2){
            return;
        }
        //过期时间小于一天，就刷新成3天
        if (expireDays<1){
            RedisUtils.expire(userTokenKey,3,TimeUnit.DAYS);
        }
    }

    /**
     * 登录成功，获取token
     *
     * @param uid
     * @return 返回token
     */
    @Override
    public String login(Long uid) {
        //生成 token令牌
        String token = jwtUtils.createToken(uid);
        //将token存到 redis中，过期时间为3天。   key---》token
        RedisUtils.set(RedisKey.getKey(RedisKey.USER_TOKEN_STR, uid), token, 3, TimeUnit.DAYS);
        return token;
    }

    /**
     * 前端传递token。后端检查token有效，返回uid。
     * 这个方法检查了 token 是否有效。
     */
    @Override
    public Long getValidUid(String token) {
        //先通过前端传递的token拿到uid
        Long uid = jwtUtils.getUidOrNull(token);
        if (Objects.isNull(uid)) {
            return null;
        }
        //再通过uid构建key，从redis中拿到token。如果为空，说明已经过期了。否则未过期，
        String oldToken = RedisUtils.getStr(RedisKey.getKey(RedisKey.USER_TOKEN_STR, uid));
        //判断两个对象是否相等。只要两个token相等那就说明没过期，不相等就是过期了。
        return Objects.equals(oldToken, token) ? uid : null;
    }
}
